﻿using System;
using System.Collections.Generic;
using System.Data;
using l1cs.server.datatables;
using l1cs.server.model.Instance;
using l1cs.server.server.types;
using MySql.Data.MySqlClient;
using l1cs.server.utils;
using System.Threading;

namespace l1cs.server.model.trap
{
    public class L1WorldTraps
    {
        private static Logger _log = Logger.getLogger( typeof( L1WorldTraps ).FullName );

        private List<L1TrapInstance> _allTraps = new List<L1TrapInstance>();

        private List<L1TrapInstance> _allBases = new List<L1TrapInstance>();

        private Timer _timer;

        private static L1WorldTraps _instance;

        public static L1WorldTraps getInstance()
        {
            if ( _instance == null )
            {
                _instance = new L1WorldTraps();
            }
            return _instance;
        }

        private L1WorldTraps()
        {
            String sqlstr = "SELECT * FROM spawnlist_trap";
            using ( MySqlWrapper wrapper = new MySqlWrapper() )
            {
                foreach ( DataRow item in wrapper.GetDataTable( sqlstr ).Rows )
                {
                    int trapId = SqlUtils.toInt( item["trapId"] );
                    L1Trap trapTemp = TrapTable.getInstance().getTemplate( trapId );
                    L1Location loc = new L1Location();
                    loc.setMap( SqlUtils.toInt( item["mapId"] ) );
                    loc.setX( SqlUtils.toInt( item["locX"] ) );
                    loc.setY( SqlUtils.toInt( item["locY"] ) );
                    Point rndPt = new Point();
                    rndPt.setX( SqlUtils.toInt( item["locRndX"] ) );
                    rndPt.setY( SqlUtils.toInt( item["locRndY"] ) );
                    int count = SqlUtils.toInt( item["count"] );
                    int span = SqlUtils.toInt( item["span"] );

                    for ( int i = 0; i < count; i++ )
                    {
                        L1TrapInstance trap = new L1TrapInstance( IdFactory.getInstance().nextId(), trapTemp, loc, rndPt, span );
                        L1World.getInstance().addVisibleObject( trap );
                        _allTraps.Add( trap );
                    }
                    L1TrapInstance l1base = new L1TrapInstance( IdFactory.getInstance().nextId(), loc );
                    L1World.getInstance().addVisibleObject( l1base );
                    _allBases.Add( l1base );
                }
            }
        }

        public static void reloadTraps()
        {
            TrapTable.reload();
            L1WorldTraps oldInstance = _instance;
            _instance = new L1WorldTraps();
            oldInstance.resetTimer();
            removeTraps( oldInstance._allTraps );
            removeTraps( oldInstance._allBases );
        }

        private static void removeTraps( List<L1TrapInstance> traps )
        {
            foreach ( L1TrapInstance trap in traps )
            {
                trap.disableTrap();
                L1World.getInstance().removeVisibleObject( trap );
            }
        }

        private void resetTimer()
        {
            lock ( this )
            {
                _timer.Dispose();
                //_timer = new Timer();
            }
        }

        private void disableTrap( L1TrapInstance trap )
        {
            trap.disableTrap();

            lock ( this )
            {
                //_timer.schedule(new TrapSpawnTimer(trap), trap.getSpan());
                _timer = new Timer( new TimerCallback( TrapSpawnTimerSub ), trap, trap.getSpan(), Timeout.Infinite );
            }
        }

        public void resetAllTraps()
        {
            foreach ( L1TrapInstance trap in _allTraps )
            {
                trap.resetLocation();
                trap.enableTrap();
            }
        }

        public void onPlayerMoved( L1PcInstance player )
        {
            L1Location loc = player.getLocation();

            foreach ( L1TrapInstance trap in _allTraps )
            {
                if ( trap.isEnable() && loc.equals( trap.getLocation() ) )
                {
                    trap.onTrod( player );
                    disableTrap( trap );
                }
            }
        }

        public void onDetection( L1PcInstance caster )
        {
            L1Location loc = caster.getLocation();

            foreach ( L1TrapInstance trap in _allTraps )
            {
                if ( trap.isEnable() && loc.isInScreen( trap.getLocation() ) )
                {
                    trap.onDetection( caster );
                    disableTrap( trap );
                }
            }
        }

        //private class TrapSpawnTimer extends TimerTask {
        //    private final L1TrapInstance _targetTrap;

        //    public TrapSpawnTimer(L1TrapInstance trap) {
        //        _targetTrap = trap;
        //    }

        //    @Override
        public void TrapSpawnTimerSub( object state )
        {
            L1TrapInstance _targetTrap = (L1TrapInstance)state;
            _targetTrap.resetLocation();
            _targetTrap.enableTrap();
        }
        //}
    }
}
